﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using OFX.Aggregator.Infrastructure;
using OFX.Aggregator.WpfApplication.Properties;

namespace OFX.Aggregator.WpfApplication
{
	/// <summary>
	/// Interaction logic for StatementSourceListPage.xaml
	/// </summary>
	public partial class StatementSourceListPage : Page
	{
		#region Commands

		public static RoutedCommand StatementSource_Config = new RoutedCommand("StatementSource_Config",
		                                                                       typeof (StatementSourceListPage));

		public static RoutedCommand StatementSource_Create = new RoutedCommand("StatementSource_Create",
		                                                                       typeof (StatementSourceListPage));

		public static RoutedCommand StatementSource_Delete = new RoutedCommand("StatementSource_Delete",
		                                                                       typeof (StatementSourceListPage));

		public static RoutedCommand StatementSource_Fetch = new RoutedCommand("StatementSource_Fetch",
		                                                                      typeof (StatementSourceListPage));

		#endregion

		#region Private Fields

		private readonly IIoCContainerAbstraction container;
		private bool workflowRunning;

		#endregion

		// Using a DependencyProperty as the backing store for StatementSources.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty StatementSourcesProperty =
			DependencyProperty.Register("StatementSources", typeof (IList<StatementSource>), typeof (StatementSourceListPage),
			                            new UIPropertyMetadata(null));

		public StatementSourceListPage()
		{
			this.container = SingletonContainer.Resolve<IIoCContainerAbstraction>();

			var statementSourceRepository = this.container.Resolve<IStatementSourceRepository>();

			StatementSources = statementSourceRepository.StatementSources;

			InitializeComponent();
		}

		public IList<StatementSource> StatementSources
		{
			get { return (IList<StatementSource>) GetValue(StatementSourcesProperty); }
			set { SetValue(StatementSourcesProperty, value); }
		}

		#region Event Handlers

		private void workflow_WorkflowStarted(object sender, EventArgs e)
		{
			Debug.Assert(!this.workflowRunning);

			var workflow = (IStatementProcessingWorkflow) sender;

			this.workflowRunning = true;
			Cursor = Cursors.Wait;
			ForceCursor = true;

			var page = this.container.Resolve<Page>("FetchStatementProgressPage",
			                                        new Dictionary<string, object> {{"source", workflow.StatementSource}});

			NavigationService.Navigate(page);
		}

		private void workflow_WorkflowFinished(object sender, EventArgs e)
		{
			var workflow = (IStatementProcessingWorkflow) sender;
			workflow.WorkflowStarted -= workflow_WorkflowStarted;
			workflow.WorkflowFinished -= workflow_WorkflowFinished;

			this.workflowRunning = false;

			Settings.Default.Save(); // Ensure the update gets registered 

			Cursor = Cursors.Arrow;
			ForceCursor = false;
		}

		#endregion

		#region Command Handlers

		private void CanFetchStatement(object sender, CanExecuteRoutedEventArgs e)
		{
			var statementSource = (StatementSource) e.Parameter;

			e.CanExecute = (statementSource != null && statementSource.Retrieval.CanRetrieveStatement && !this.workflowRunning);
		}

		private void FetchStatement(object sender, ExecutedRoutedEventArgs e)
		{
			var statementSource = (StatementSource) e.Parameter;                                         
			if (statementSource != null)
			{
				var workflow =
					this.container.Resolve<IStatementProcessingWorkflow>(new Dictionary<string, object>
					                                                     	{{"statementSource", statementSource}});

				workflow.WorkflowStarted += workflow_WorkflowStarted;
				workflow.WorkflowFinished += workflow_WorkflowFinished;
				workflow.PerformWorkflow();
			}
		}

		private void CanDeleteStatementSource(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = (e.Parameter != null && ((ICollection) e.Parameter).Count != 0 && !this.workflowRunning);
		}

		private void DeleteStatementSource(object sender, ExecutedRoutedEventArgs e)
		{
			foreach (StatementSource statementSource in new ArrayList((ICollection)e.Parameter))
			{
				StatementSources.Remove(statementSource);
			}
		}

		private void CanConfigStatementSource(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = (e.Parameter is StatementSource && !this.workflowRunning);
		}

		private void ConfigStatementSource(object sender, ExecutedRoutedEventArgs e)
		{
			var statementSource = (StatementSource) e.Parameter;
			var page =
				this.container.Resolve<AccountSetupPage>(new Dictionary<string, object> {{"statementSourceToEdit", statementSource}});

			NavigationService.Navigate(page);
		}

		private void CanCreateStatementSource(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = true;
		}

		private void CreateStatementSource(object sender, ExecutedRoutedEventArgs e)
		{
			var page = this.container.Resolve<AccountTypeSelectionPage>();
			NavigationService.Navigate(page);
		}

		#endregion
	}
}